#include "classes/MapClass.hpp"
#include "classes/PlayerClass.hpp"
#include "classes/ContentManager.hpp"
MapClass::MapClass()
{
    for(int anX=0; anX<MAP_WIDTH; anX++)
    {
        for(int anY=0; anY<MAP_HEIGHT; anY++)
        {
            for(int anZ=0; anZ<MAP_DEPTH; anZ++)
            {
                mRooms[anX][anY][anZ].Description="";
                mRooms[anX][anY][anZ].NonRoom=true;
            }
        }
    }
}

MapClass::~MapClass()
{

}

void MapClass::MakeDungeon()
{
    unsigned int RoomChance=gConfig->GetUint32("MapGen","Rooms",3);
    unsigned int ExitChance=gConfig->GetUint32("MapGen","Doors",2);
	unsigned int StairChance=gConfig->GetUint32("MapGen","Stairs",1);
	unsigned int ItemChance=gConfig->GetUint32("MapGen","Items",1);
	unsigned int anRand=0;
	unsigned int anX, anY,anZ;

    //
    //first pass
    for(anX=0; anX<MAP_WIDTH; anX+=2)
    {
        for(anY=0; anY<MAP_HEIGHT; anY+=2)
        {
            for(anZ=0; anZ<MAP_DEPTH; anZ++)
            {
                PlaceRoom(anX,anY,anZ);
            }
        }
    }
    //second (randomized) pass
    for(anX=0; anX<MAP_WIDTH; anX++)
    {
        for(anY=0; anY<MAP_HEIGHT; anY++)
        {
            for(anZ=0; anZ<MAP_DEPTH; anZ++)
            {
                if(mRooms[anX][anY][anZ].NonRoom==true)
                {
                    anRand=sf::Randomizer::Random(1,10);
                    if(anRand<=RoomChance)
                    {
                        PlaceRoom(anX,anY,anZ);
                    }
                }
            }
        }
    }
	//third pass for doors (randomized) pass
    for(anX=0; anX<MAP_WIDTH; anX++)
    {
        for(anY=0; anY<MAP_HEIGHT; anY++)
        {
            for(anZ=0; anZ<MAP_DEPTH; anZ++)
            {
                if(mRooms[anX][anY][anZ].NonRoom==false)
                {
					//West
                    anRand=sf::Randomizer::Random(1,10);
					if(anX>0 && anRand<ExitChance)
					{
						if(mRooms[anX-1][anY][anZ].NonRoom==false && mRooms[anX-1][anY][anZ].EastExit.isOpen==false )
						{
							//West Exit
							mRooms[anX][anY][anZ].WestExit.Room=sf::Vector3i(anX-1,anY,anZ);
							mRooms[anX][anY][anZ].WestExit.Description="An Open Doorway is to The West.";
							mRooms[anX][anY][anZ].WestExit.isOpen=true;
							//East exit back.
							mRooms[anX-1][anY][anZ].EastExit.Room=sf::Vector3i(anX,anY,anZ);
							mRooms[anX-1][anY][anZ].EastExit.Description="An Open Doorway is to The East.";
							mRooms[anX-1][anY][anZ].EastExit.isOpen=true;
						}
					}
					//South
					anRand=sf::Randomizer::Random(1,10);
					if(anY<MAP_HEIGHT-1 && anRand<ExitChance)
					{
						if(mRooms[anX][anY+1][anZ].NonRoom==false && mRooms[anX][anY+1][anZ].NorthExit.isOpen==false )
						{
							//South Exit
							mRooms[anX][anY][anZ].SouthExit.Room=sf::Vector3i(anX,anY+1,anZ);
							mRooms[anX][anY][anZ].SouthExit.Description="An Open Doorway is to The South.";
							mRooms[anX][anY][anZ].SouthExit.isOpen=true;
							//North exit back.
							mRooms[anX][anY+1][anZ].NorthExit.Room=sf::Vector3i(anX,anY,anZ);
							mRooms[anX][anY+1][anZ].NorthExit.Description="An Open Doorway is to The North.";
							mRooms[anX][anY+1][anZ].NorthExit.isOpen=true;
						}
					}
					//East
					anRand=sf::Randomizer::Random(1,10);
					if(anX<MAP_WIDTH-1 && anRand<ExitChance)
					{
						if(mRooms[anX+1][anY][anZ].NonRoom==false && mRooms[anX+1][anY][anZ].WestExit.isOpen==false )
						{
							//East Exit
							mRooms[anX][anY][anZ].EastExit.Room=sf::Vector3i(anX+1,anY,anZ);
							mRooms[anX][anY][anZ].EastExit.Description="An Open Doorway is to The East.";
							mRooms[anX][anY][anZ].EastExit.isOpen=true;
							//West exit back.
							mRooms[anX+1][anY][anZ].WestExit.Room=sf::Vector3i(anX,anY,anZ);
							mRooms[anX+1][anY][anZ].WestExit.Description="An Open Doorway is to The West.";
							mRooms[anX+1][anY][anZ].WestExit.isOpen=true;
						}
					}
					//North
                    anRand=sf::Randomizer::Random(1,10);
					if(anY>0 && anRand<ExitChance)
					{
						if(mRooms[anX][anY-1][anZ].NonRoom==false && mRooms[anX][anY-1][anZ].SouthExit.isOpen==false )
						{
							//North Exit
							mRooms[anX][anY][anZ].NorthExit.Room=sf::Vector3i(anX,anY-1,anZ);
							mRooms[anX][anY][anZ].NorthExit.Description="An Open Doorway is to The North.";
							mRooms[anX][anY][anZ].NorthExit.isOpen=true;
							//East exit South.
							mRooms[anX][anY-1][anZ].SouthExit.Room=sf::Vector3i(anX,anY,anZ);
							mRooms[anX][anY-1][anZ].SouthExit.Description="An Open Doorway is to The South.";
							mRooms[anX][anY-1][anZ].SouthExit.isOpen=true;
						}
					}
                }
            }
        }
    }
    //fourth pass for Stairs (randomized) pass
    for(anX=0; anX<MAP_WIDTH; anX++)
    {
        for(anY=0; anY<MAP_HEIGHT; anY++)
        {
            for(anZ=0; anZ<MAP_DEPTH; anZ++)
            {
                if(mRooms[anX][anY][anZ].NonRoom==false)
                {
					//Up
                    anRand=sf::Randomizer::Random(1,10);
					if(anZ>0 && anRand<StairChance)
					{
						if(mRooms[anX][anY][anZ-1].NonRoom==false && mRooms[anX][anY][anZ-1].DownExit.isOpen==false )
						{
							//Up Exit
							mRooms[anX][anY][anZ].UpExit.Room=sf::Vector3i(anX,anY,anZ-1);
							mRooms[anX][anY][anZ].UpExit.Description="There is a stairway loading Up.";
							mRooms[anX][anY][anZ].UpExit.isOpen=true;
							//Down exit back.
							mRooms[anX][anY][anZ-1].DownExit.Room=sf::Vector3i(anX,anY,anZ);
							mRooms[anX][anY][anZ-1].DownExit.Description="There is a stairway loading Down.";
							mRooms[anX][anY][anZ-1].DownExit.isOpen=true;
						}
					}
					//Down
					anRand=sf::Randomizer::Random(1,10);
					if(anZ<MAP_DEPTH-1 && anRand<StairChance)
					{
						if(mRooms[anX][anY][anZ+1].NonRoom==false && mRooms[anX][anY][anZ+1].UpExit.isOpen==false )
						{
							//Down Exit
							mRooms[anX][anY][anZ].DownExit.Room=sf::Vector3i(anX,anY,anZ+1);
							mRooms[anX][anY][anZ].DownExit.Description="There is a stairway loading Down.";
							mRooms[anX][anY][anZ].DownExit.isOpen=true;
							//North exit back.
							mRooms[anX][anY][anZ+1].UpExit.Room=sf::Vector3i(anX,anY,anZ);
							mRooms[anX][anY][anZ+1].UpExit.Description="There is a stairway loading Up.";
							mRooms[anX][anY][anZ+1].UpExit.isOpen=true;
						}
					}
                }
            }
        }
    }
    //fourth pass for Stairs (randomized) pass
    for(anX=0; anX<MAP_WIDTH; anX++)
    {
        for(anY=0; anY<MAP_HEIGHT; anY++)
        {
            for(anZ=0; anZ<MAP_DEPTH; anZ++)
            {
                if(mRooms[anX][anY][anZ].NonRoom==false)
                {
                    anRand=sf::Randomizer::Random(1,10);
					if(anZ<MAP_DEPTH-1 && anRand<=ItemChance)
					{

					}
                }
            }
        }
    }
    PlacePlayer(0,0);
}

void MapClass::PlaceRoom(int theX, int theY, int theZ)
{
    mRooms[theX][theY][theZ].Description=gContent->GetRandDescription(0);
    mRooms[theX][theY][theZ].NonRoom=false;
	mRooms[theX][theY][theZ].NorthExit.isOpen=false;
	mRooms[theX][theY][theZ].EastExit.isOpen=false;
	mRooms[theX][theY][theZ].SouthExit.isOpen=false;
	mRooms[theX][theY][theZ].WestExit.isOpen=false;
	mRooms[theX][theY][theZ].DownExit.isOpen=false;
	mRooms[theX][theY][theZ].UpExit.isOpen=false;
}
void MapClass::PlacePlayer(int theX, int theY)
{
    if(gPlayer!=NULL)
    {
        gPlayer->SetCoords(sf::Vector3i(theX,theY,0));
    }
}
void MapClass::PrintLevel(int theZ)
{
    std::string line;
    //second (randomized) pass
    for(int anY=0; anY<MAP_HEIGHT; anY++)
    {
        line="";
        for(int anX=0; anX<MAP_WIDTH; anX++)
        {
            if(gPlayer->GetCoords().x==anX&&gPlayer->GetCoords().y==anY&&gPlayer->GetCoords().z==theZ)
            {
                line+="P";
            }
            else if(mRooms[anX][anY][theZ].UpExit.isOpen&&mRooms[anX][anY][theZ].DownExit.isOpen)
            {
                line+="X";
            }
            else if(mRooms[anX][anY][theZ].UpExit.isOpen)
            {
                line+=">";
            }
            else if(mRooms[anX][anY][theZ].DownExit.isOpen)
            {
                line+="<";
            }
            else if(mRooms[anX][anY][theZ].NonRoom==false)
            {
                line+="#";
            }
            else
            {
                line+=".";
            }
        }
        gMainWindow->NewLine(line);
    }
}
void MapClass::GiveItem(typeItem theItem,unsigned int theAmount, int theX, int theY, int theZ)
{
    typeItemRef newItem;
    newItem.Item=theItem;
    newItem.Amount=theAmount;
    newItem.Inventory=&mRooms[theX][theY][theZ].Inventory;
    int anIndex;
    if(newItem.Item.Stackable=="Yes" )
    {
        for(anIndex=0;anIndex<newItem.Inventory->size();anIndex++)
        {
            if(newItem.Inventory->at(anIndex).Item.Name==newItem.Item.Name)
            {
                newItem.Inventory->at(anIndex).Amount++;
                return;
            }
        }
    }
    if(newItem.Inventory->size()>PLAYER_ITEMS)
    {
        return;
    }
    newItem.Index=newItem.Inventory->size();
    newItem.Inventory->push_back(newItem);
}